coroutine = function(func) {
	return function() {	
		if (suspendedFrame && suspendedFrame._r.thread == currentThread && suspendedFrame._r.func) {
				var frame = suspendedFrame;
				var gen = frame._r;
				delete gen.thread;
	
				suspendedFrame = gen.childFrame; // if this is undefined it means we are at the top of the resume stack
				delete gen.childFrame; // for assertions
				var result = suspendedFrame._r.func(); // resume the stack
				if (result == Suspend) return frame._s(); // if we have to suspend again right away
		}
		else { //fresh entry
			var gen = func.apply(this,arguments);
			if (!(gen != null && typeof(gen) == 'object' &&
					typeof(gen.next) == 'function' && typeof(gen.send) == 'function'))
				return gen;
			var frame = new CallFrame;
			frame._r = gen;
			frame._r.func = arguments.callee;
			var result;
		}
		try{
			while(1){
				coreturn = undefined; // global return value
				result = gen.send(result);
				if (result == Suspend) return frame._s();
			} 
		} catch(e if e == StopIteration) {
			return coreturn;
		}		
	}
}
